package com.module.ble.widget

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
import android.graphics.DashPathEffect
import android.graphics.LinearGradient
import android.graphics.Paint
import android.graphics.Path
import android.graphics.Point
import android.graphics.Rect
import android.graphics.Shader
import android.graphics.Typeface
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.view.ViewConfiguration
import com.common.base.app.extras.dp2px
import com.common.base.utils.ViewUtils.getColor
import com.module.ble.R
import com.module.ble.data.bean.CusChartData
import kotlin.math.abs
import kotlin.math.roundToInt

/**
 *
 * 作者：sosou
 *
 * 版本：1.0
 *
 * 创建日期：2024/10/24
 *
 * 描述：日图表
 *
 * 修订历史：
 *
 */
class HeartDayChartOld(context: Context, attrs: AttributeSet?) : View(context,attrs){
    //屏幕宽高
    private var scrWidth = 0f
    private var scrHeight = 0f
    private var xData: Array<String> = arrayOf("00", "06", "12", "18", "24")
    private var yData: Array<Int> = arrayOf(200, 150, 100, 50, 0)
    private var heartData = mutableListOf<CusChartData>()
    private lateinit var paintLine: Paint //y轴线
    private lateinit var paintGradientLine: Paint //指示渐变竖线
    private lateinit var paintXText: Paint //x轴坐标
    private lateinit var paintYText: Paint //y轴坐标
    private lateinit var coordinatePoint: Paint //坐标点
    private lateinit var paintSolidLine: Paint// 实线的画笔
    private lateinit var paintPolyline: Paint //心率折线
    private lateinit var paintPolyShadow: Paint //心率折线阴影
    private lateinit var paintRound: Paint  //指示滑块圆
    private lateinit var paintBessel: Paint  //滑块底部

    private var xSlider = 0f //滑块的x轴位置

    private var mLinePath: Path  //折线路径

    private val curveCircleRadius = 12f
    private var mPath: Path  //滑块贝塞尔

    //第一条曲线的坐标
    private val mFirstCurveStartPoint = Point()
    private val mFirstCurveEndPoint = Point()
    private val mFirstCurveControlPoint1 = Point()
    private val mFirstCurveControlPoint2 = Point()

    //第二条曲线的坐标
    private var mSecondCurveStartPoint = Point()
    private val mSecondCurveEndPoint = Point()
    private val mSecondCurveControlPoint1 = Point()
    private val mSecondCurveControlPoint2 = Point()

    private var isRest = false //是否静息
    private var restHeart = 0 //静息值

    private val margin = 20f //左右两边距离
    private var xWithStart = 0f //x轴的起始点
    private var xWithEnd = 0f  //x轴结束点
    private var ySpacing = 0f //高度分割份数后间距
    private var xSpacing = 0f //x轴柱子分割份数后间距
    private var xTextSpacing = 0f //x轴文字分割份数后间距

    // 添加属性来缓存计算结果
    private var lastIndex = -1
    private val touchSlop = ViewConfiguration.get(context).scaledTouchSlop
    // 优化Path对象的重用
    private val tmpPath = Path()
    // 添加属性来缓存shader
    private var polyShadowShader: Shader? = null
    // 添加控制变量
    private var showZeroLine = true // 控制是否显示0刻度线

    private val paintPolylineDefaultColor = getColor(R.color.c_2a7fd8)
    private var maxGapForConnection = 20 // 间隔阈值默认值为5
    // 添加控制变量
    private var showSlider = false

    private var showYAxisLabels = true  // 控制是否显示Y轴文字
    private val yAxisTextPadding = dp2px(8f)  // 文字左边的间距// 添加一个属性来存储最大文字宽度
    private var maxYAxisTextWidth = 0f

    init {
        setLayerType(LAYER_TYPE_SOFTWARE, null)
        // 设置绘制缓存
        isDrawingCacheEnabled = true

        // 避免不必要的父布局请求
        setWillNotDraw(false)
        mLinePath = Path()
        mPath = Path()
        initPaint()
    }

    /**
     * 初始化画笔
     */
    private fun initPaint() {

        paintLine = Paint().apply {
            style = Paint.Style.STROKE
            strokeWidth = 1f
            color = getColor(R.color.c_2e2e2e)
            // 设置虚线效果
            // 第一个参数数组表示虚线的格式：[实线长度, 空白长度]
            // 第二个参数表示偏移量
//            pathEffect = DashPathEffect(floatArrayOf(8f, 4f), 0f)
            // 更长的虚线
            pathEffect = DashPathEffect(floatArrayOf(12f, 6f), 0f)
            // 或者不规则的虚线
//            pathEffect = DashPathEffect(floatArrayOf(10f, 5f, 5f, 5f), 0f)
        }


        paintGradientLine = Paint()
        paintGradientLine.style = Paint.Style.STROKE
        paintGradientLine.strokeWidth = 2f

        paintPolyShadow = Paint()
        paintPolyShadow.style = Paint.Style.FILL

        paintXText = Paint()
        paintXText.isAntiAlias = true
        paintXText.strokeWidth = 1f
        paintXText.textSize = dp2px(12f)
        paintXText.textAlign = Paint.Align.CENTER
        paintXText.color = getColor(R.color.black)

        paintYText = Paint()
        paintYText.isAntiAlias = true
        paintYText.textSize = dp2px(11f)
        paintYText.strokeWidth = 1f
        paintYText.textAlign = Paint.Align.RIGHT
        paintYText.color = getColor(R.color.color_808080)

        // 虚线画笔(原来的paintPolyline)
        paintPolyline = Paint().apply {
            style = Paint.Style.FILL
            strokeWidth = 3f
            isAntiAlias = true
            pathEffect = DashPathEffect(floatArrayOf(3f, 3f), 0f)
            color = paintPolylineDefaultColor
        }

        // 新增实线画笔
        paintSolidLine = Paint().apply {
            style = Paint.Style.FILL
            strokeWidth = 3f
            isAntiAlias = true
            color = paintPolylineDefaultColor
        }

        paintRound = Paint()
        paintRound.style = Paint.Style.FILL
        paintRound.isAntiAlias = true
        paintRound.color = getColor(R.color.color_3683FF)

        paintBessel = Paint()
        paintBessel.style = Paint.Style.FILL
        paintBessel.isAntiAlias = true
        paintBessel.color = getColor(R.color.red)

        coordinatePoint = Paint()
        coordinatePoint.style = Paint.Style.FILL
        coordinatePoint.strokeWidth = 3f
        coordinatePoint.isAntiAlias = true
        coordinatePoint.color = paintPolylineDefaultColor
    }

    // 添加一个方法来计算最大文字宽度
    private fun calculateMaxYAxisTextWidth() {
        maxYAxisTextWidth = yData.map { value ->
            paintYText.measureText(value.toString())
        }.maxOrNull() ?: 0f

        // 如果有静息心率，也要考虑其宽度
        if (isRest && restHeart > 0) {
            val restHeartWidth = paintYText.measureText(restHeart.toString())
            maxYAxisTextWidth = maxOf(maxYAxisTextWidth, restHeartWidth)
        }
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        scrWidth = width.toFloat()
        scrHeight = height.toFloat()

        val chartHeight = height * 1.05f
        ySpacing = chartHeight / 6f

        updateChartDimensions()
        xSlider = xWithStart
    }

    private var mDownX = 0f
    private var mDownY = 0f

    private var isSlider = false//是否开启触摸模式

    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(event: MotionEvent): Boolean {
        if (!showSlider) return false

        if (heartData.isNullOrEmpty()) return true//无数据是直接透传触摸

        val bottomY = ySpacing * 5.3f
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                mDownX = event.x
                mDownY = event.y
                // 扩大触摸判定区域
                isSlider = abs(event.x - xSlider) < 100f && abs(event.y - bottomY) < 100f
                return true
            }
            MotionEvent.ACTION_MOVE -> {
                if (isSlider) {
                    // 限制滑动范围
                    xSlider = event.x.coerceIn(xWithStart, xWithEnd)

                    // 优化数值查找逻辑
                    val index = ((xSlider - xWithStart) / xSpacing).toInt()
                        .coerceIn(0, heartData.size - 1)
                    if (index in heartData.indices) {
                        onDaySelectListener?.invoke(heartData[index].createdTime, heartData[index].mValue)
                    }

                    invalidate()
                    return true
                }
            }
            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                if (isSlider) {
                    // 计算当前位置对应的索引
                    val currentIndex = ((xSlider - xWithStart) / xSpacing).roundToInt()
                        .coerceIn(0, heartData.size - 1)

                    // 查找最近的有效数据点
                    val nearestValidIndex = findNearestValidIndex(currentIndex)

                    // 如果找到有效点，将滑块吸附到该点
                    if (nearestValidIndex != -1) {
                        xSlider = xWithStart + nearestValidIndex * xSpacing
                        if (nearestValidIndex in heartData.indices) {
                            onDaySelectListener?.invoke(
                                heartData[nearestValidIndex].createdTime,
                                heartData[nearestValidIndex].mValue
                            )
                        }
                    }

                    invalidate()
                } else {
                    // 点击切换逻辑
                    if (abs(event.x - mDownX) > xSpacing) {
                        onDayMoveListener?.invoke(event.x > mDownX)
                    } else {
                        val targetIndex = ((event.x - xWithStart) / xSpacing).roundToInt()
                            .coerceIn(0, heartData.size - 1)
                        // 同样找最近的有效点
                        val nearestValidIndex = findNearestValidIndex(targetIndex)
                        if (nearestValidIndex != -1) {
                            xSlider = xWithStart + nearestValidIndex * xSpacing
                            invalidate()
                        }
                    }
                }
                return true
            }
        }
        return super.onTouchEvent(event)
    }
    private fun findNearestValidIndex(currentIndex: Int): Int {
        if (currentIndex >= heartData.size) return -1

        // 如果当前位置就是有效点，直接返回
        if (heartData[currentIndex].mValue > 0) {
            return currentIndex
        }

        var leftIndex = currentIndex
        var rightIndex = currentIndex
        val maxSearch = 50 // 设置最大搜索范围，避免过度搜索

        // 向左右同时搜索最近的有效点
        for (i in 1..maxSearch) {
            leftIndex--
            rightIndex++

            // 检查左侧点
            if (leftIndex >= 0 && heartData[leftIndex].mValue > 0) {
                return leftIndex
            }

            // 检查右侧点
            if (rightIndex < heartData.size && heartData[rightIndex].mValue > 0) {
                return rightIndex
            }

            // 如果已经超出数据范围，停止搜索
            if (leftIndex < 0 && rightIndex >= heartData.size) {
                break
            }
        }

        // 如果没找到有效点，返回原位置
        return currentIndex
    }

    @SuppressLint("DrawAllocation")
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        // 使用clipRect减少不必要的绘制区域
        canvas.save()
        canvas.clipRect(0f, 0f, scrWidth, scrHeight)

        //画y轴方向横线与文字
        drawY(canvas)
        //折线
        drawPolyline(canvas)
        //垂直渐变线
        drawGradientLine(canvas)
        //底部
        drawBessel(canvas)
        //画x轴方向文字
        drawX(canvas)

        canvas.restore()
    }

    private fun drawX(canvas: Canvas) {
        xData.forEachIndexed { index, s ->
            val x = xWithStart + xTextSpacing * index

            if (showSlider) {
                // 原有的滑块模式下的文字绘制逻辑
                val dis = abs(x - xSlider)
                val besselTopY = ySpacing * 5.3f - curveCircleRadius * 1.7f
                var y = besselTopY + paintXText.textSize / 2

                if (dis < xTextSpacing / 2) {
                    paintXText.typeface = Typeface.DEFAULT_BOLD
                    val liftRatio = (1 - dis / (xTextSpacing / 2)).coerceIn(0f, 1f)
                    val liftDistance = 32f
                    y -= liftDistance * liftRatio
                } else {
                    paintXText.typeface = Typeface.DEFAULT
                }

                canvas.drawText(s, x, y, paintXText)
            } else {
                // 无滑块模式下的文字绘制逻辑
                paintXText.typeface = Typeface.DEFAULT
                // 直接在底部绘制文字，设置一个固定的底部边距
                val y = height - dp2px(10f)
                canvas.drawText(s, x, y, paintXText)
            }
        }
    }

    private fun drawPolyline(canvas: Canvas) {
        val validPoints = heartData.mapIndexedNotNull { index, data ->
            if (data.mValue > 0) index to data.mValue else null
        }

        if (validPoints.isEmpty()) {
            Log.d("HeartRateChart", "No valid points to draw")
            return
        }

        // 如果有多个点，绘制连线和阴影
        if (validPoints.size > 1) {
            // 绘制连续点之间的线段和阴影
            validPoints.zipWithNext().forEach { (current, next) ->
                val (currentIndex, currentValue) = current
                val (nextIndex, nextValue) = next

                val x0 = xWithStart + (currentIndex * xSpacing)
                val y0 = ySpacing * 5f - ySpacing * (currentValue / 50f)
                val x1 = xWithStart + (nextIndex * xSpacing)
                val y1 = ySpacing * 5f - ySpacing * (nextValue / 50f)

                // 计算两点之间的间隔
                val gap = nextIndex - currentIndex
                val isConnected = gap <= maxGapForConnection

                // 选择使用的画笔
                val linePaint = if (isConnected) {
                    paintSolidLine.apply {
                        color = if (isRest) getColor(R.color.c_656565) else paintPolylineDefaultColor
                    }
                } else {
                    paintPolyline.apply {
                        color = if (isRest) getColor(R.color.c_656565) else paintPolylineDefaultColor
                    }
                }

                // 只在连续数据时绘制阴影
                if (isConnected) {
                    drawPolyShadow(x0, y0, x1, y1, canvas)
                }

                // 绘制折线
                canvas.drawLine(x0, y0, x1, y1, linePaint)
            }

            // 为最后一个点添加延伸阴影
            val (lastIndex, lastValue) = validPoints.last()
            val x = xWithStart + (lastIndex * xSpacing)
            val y = ySpacing * 5f - ySpacing * (lastValue / 50f)
            // 延伸一定距离，可以根据需要调整
            val extendedX = x + xSpacing * 2
            drawPolyShadow(x, y, extendedX, y, canvas)

        } else {
            // 如果只有一个点的处理
            val (index, value) = validPoints.first()
            val x = xWithStart + (index * xSpacing)
            val y = ySpacing * 5f - ySpacing * (value / 50f)
            // 绘制点
            canvas.drawCircle(x, y, 4f, paintSolidLine)
            // 为单个点添加阴影
            val extendedX = x + xSpacing * 2
            drawPolyShadow(x, y, extendedX, y, canvas)
        }

        // 绘制选中点的指示器
        if (showSlider) {  // 只在显示滑块时绘制指示器
            validPoints.forEach { (index, value) ->
                val x = xWithStart + (index * xSpacing)
                val y = ySpacing * 5f - ySpacing * (value / 50f)

                if (abs(x - xSlider) < xSpacing / 2 && !isRest) {
                    coordinatePoint.color = getColor(R.color.white)
                    canvas.drawCircle(x, y, 10f, coordinatePoint)
                    coordinatePoint.color = getColor(R.color.c_5bfdb9)
                    canvas.drawCircle(x, y, 7f, coordinatePoint)
                    onDaySelectListener?.invoke(heartData[index].createdTime, value)
                }
            }
        }

        // 绘制静息心率线
        if (isRest && restHeart > 0) {
            paintSolidLine.color = paintPolylineDefaultColor
            val restY = ySpacing * 5f - ySpacing * (restHeart / 50f)
            canvas.drawLine(margin, restY, scrWidth - margin, restY, paintSolidLine)
        }
    }

    private fun drawY(canvas: Canvas) {
        val y = ySpacing * 5f - ySpacing * (restHeart / 50f)

        for (i in 0..4) {
            val lineY = ySpacing * (i + 1)
            val text = yData[i].toString()

            // 计算文字尺寸
            val textBounds = Rect()
            paintYText.getTextBounds(text, 0, text.length, textBounds)
            val textHeight = textBounds.height()
            val currentTextWidth = paintYText.measureText(text)

            // 计算文字在统一宽度内的居中位置
            val textAreaStartX = scrWidth - margin - maxYAxisTextWidth
            val textX = textAreaStartX + (maxYAxisTextWidth - currentTextWidth) / 2

            // 计算线条的结束位置
            val lineEndX = if (showYAxisLabels) {
                textAreaStartX - yAxisTextPadding
            } else {
                scrWidth - margin
            }

            // 判断是否是0刻度线
            if (i == 4) {
                if (showZeroLine) {
                    canvas.drawLine(margin, lineY, lineEndX, lineY, paintLine)

                    if (showYAxisLabels) {
                        paintYText.color = getColor(R.color.color_808080)
                        if (!isRest || abs(y - lineY) > 25) {
                            val textY = lineY + textHeight / 2
                            // 使用Paint.Align.LEFT，因为我们自己计算了居中位置
                            paintYText.textAlign = Paint.Align.LEFT
                            canvas.drawText(text, textX, textY, paintYText)
                        }
                    }
                }
            } else {
                canvas.drawLine(margin, lineY, lineEndX, lineY, paintLine)

                if (showYAxisLabels) {
                    paintYText.color = getColor(R.color.color_808080)
                    if (!isRest || abs(y - lineY) > 25) {
                        val textY = lineY + textHeight / 2
                        paintYText.textAlign = Paint.Align.LEFT
                        canvas.drawText(text, textX, textY, paintYText)
                    }
                }
            }
        }

        // 绘制静息心率文字
        if (isRest && restHeart > 0 && showYAxisLabels) {
            paintYText.color = getColor(R.color.c_5bfdb9)
            val text = restHeart.toString()
            val textBounds = Rect()
            paintYText.getTextBounds(text, 0, text.length, textBounds)
            val textHeight = textBounds.height()
            val currentTextWidth = paintYText.measureText(text)

            // 计算静息心率文字的居中位置
            val textAreaStartX = scrWidth - margin - maxYAxisTextWidth
            val textX = textAreaStartX + (maxYAxisTextWidth - currentTextWidth) / 2

            val textY = y + textHeight / 2
            paintYText.textAlign = Paint.Align.LEFT
            canvas.drawText(text, textX, textY, paintYText)
        }
    }

    private fun drawBessel(canvas: Canvas) {
        // 如果不显示滑块，直接返回
        if (!showSlider) return

        //系数值增大滑块位置下移,减小则会使滑块位置上移
        val bottomY = ySpacing * 5.4f

        // 微调贝塞尔曲线参数
        val blueCircleRadius = curveCircleRadius * 1.8f
        // 减小曲线凸起高度，使文字更贴近
        val curveHeight = blueCircleRadius * 0.6f
        val curveWidth = blueCircleRadius * 3.8f

        // 调整圆点位置，减小乘数使圆点位置略微上移(直接减小circleY的值来使圆点上移10px)
        val circleY = bottomY + blueCircleRadius * 0.4f-10f

        // 第一条曲线的起始点和控制点设置
        mFirstCurveStartPoint[(xSlider - curveWidth).toInt()] = bottomY.toInt()
        mFirstCurveEndPoint[xSlider.toInt()] = (circleY - blueCircleRadius - curveHeight).toInt()
        mSecondCurveStartPoint = mFirstCurveEndPoint
        mSecondCurveEndPoint[(xSlider + curveWidth).toInt()] = bottomY.toInt()

        // 控制点调整，使曲线更平滑
        mFirstCurveControlPoint1[(mFirstCurveStartPoint.x + curveWidth * 0.4f).toInt()] =
            mFirstCurveStartPoint.y
        mFirstCurveControlPoint2[(mFirstCurveEndPoint.x - curveWidth * 0.4f).toInt()] =
            mFirstCurveEndPoint.y

        mSecondCurveControlPoint1[(mSecondCurveStartPoint.x + curveWidth * 0.4f).toInt()] =
            mSecondCurveStartPoint.y
        mSecondCurveControlPoint2[(mSecondCurveEndPoint.x - curveWidth * 0.4f).toInt()] =
            mSecondCurveEndPoint.y

        // 绘制贝塞尔曲线路径
        mPath.reset()
        mPath.moveTo(0f, bottomY)
        mPath.lineTo(mFirstCurveStartPoint.x.toFloat(), mFirstCurveStartPoint.y.toFloat())
        mPath.cubicTo(
            mFirstCurveControlPoint1.x.toFloat(), mFirstCurveControlPoint1.y.toFloat(),
            mFirstCurveControlPoint2.x.toFloat(), mFirstCurveControlPoint2.y.toFloat(),
            mFirstCurveEndPoint.x.toFloat(), mFirstCurveEndPoint.y.toFloat()
        )
        mPath.cubicTo(
            mSecondCurveControlPoint1.x.toFloat(), mSecondCurveControlPoint1.y.toFloat(),
            mSecondCurveControlPoint2.x.toFloat(), mSecondCurveControlPoint2.y.toFloat(),
            mSecondCurveEndPoint.x.toFloat(), mSecondCurveEndPoint.y.toFloat()
        )
        mPath.lineTo(scrWidth, bottomY)
        mPath.lineTo(scrWidth, scrHeight)
        mPath.lineTo(0f, scrHeight)
        mPath.close()

        // 绘制路径和圆点
        canvas.drawPath(mPath, paintBessel)
        canvas.drawCircle(xSlider, circleY, blueCircleRadius, paintRound)
    }

    private fun drawPolyShadow(x0: Float, y0: Float, x1: Float, y1: Float, canvas: Canvas) {
        tmpPath.reset()
        tmpPath.moveTo(x0, ySpacing * 5f)
        tmpPath.lineTo(x0, y0)
        tmpPath.lineTo(x1, y1)
        tmpPath.lineTo(x1, ySpacing * 5f)
        tmpPath.close()

        // 缓存渐变shader
        if (polyShadowShader == null) {
            polyShadowShader = LinearGradient(
                0f,
                ySpacing * 5f - ySpacing * ((heartData.maxOfOrNull { it.mValue } ?: 0f) / 50f),
                0f,
                ySpacing * 5f,
                intArrayOf(
                    if (isRest) getColor(R.color.transparent) else getColor(R.color.c_4b94f0),
                    getColor(R.color.transparent)
                ),
                null,
                Shader.TileMode.MIRROR
            )
        }
        paintPolyShadow.shader = polyShadowShader
        canvas.drawPath(tmpPath, paintPolyShadow)
    }

    fun setValue(value: List<CusChartData>, restHeart: Int=0, resetPosition: Boolean = true): HeartDayChartOld {
        this.restHeart = restHeart
        heartData.clear()
        heartData = value.take(1440).toMutableList()

        val firstValidIndex = heartData.indexOfFirst { it.mValue > 0 }

        if (resetPosition && firstValidIndex != -1) {
            xSlider = xWithStart + (firstValidIndex * xSpacing)
            Log.d("HeartRateChart", "New xSlider position: $xSlider")
        }

        polyShadowShader = null
        lastIndex = -1
        invalidate()
        return this
    }

    fun setRest(isRest: Boolean) {
        this.isRest = isRest
        postInvalidate()
    }

    private fun drawGradientLine(canvas: Canvas) {//渐变竖线
        if (!showSlider) return  // 如果不显示滑块，直接返回

        // 可以通过调整这些系数来微调长度和位置
        val startRatio = 1f  // 增大这个值会让线条起点更低
        val endRatio = 4.8f    // 减小这个值会让线条终点更高

        val startY = ySpacing * startRatio
        val endY = ySpacing * endRatio

        val mLinearGradient = LinearGradient(
            xSlider, startY, xSlider, endY,
            intArrayOf(
                getColor(R.color.transparent),
                getColor(R.color.c_5bfdb9),
                getColor(R.color.transparent)
            ), null, Shader.TileMode.MIRROR
        )
        paintGradientLine.shader = mLinearGradient

        if (ySpacing > 0) {
            canvas.drawLine(xSlider, startY, xSlider, endY, paintGradientLine)
        }
    }

    // 更新图表尺寸的方法
    private fun updateChartDimensions() {
        if (width == 0) return

        // 确保已经计算了最大文字宽度
        calculateMaxYAxisTextWidth()

        xWithStart = margin + paintXText.measureText(xData[0]) / 2
        // 根据是否显示Y轴文字调整结束位置
        xWithEnd = if (showYAxisLabels) {
            scrWidth - margin - maxYAxisTextWidth - yAxisTextPadding
        } else {
            scrWidth - margin
        }

        val totalWidth = xWithEnd - xWithStart
        xTextSpacing = totalWidth / (xData.size - 1)
        xSpacing = totalWidth / 1439f
    }

    private var onDaySelectListener: ((time: Long, heart: Float) -> Unit)? = null

    fun setOnDaySelectListener(l: ((time: Long, heart: Float) -> Unit)): HeartDayChartOld {
        this.onDaySelectListener = l
        return this
    }

    private var onDayMoveListener: ((isPre: Boolean) -> Unit)? = null

    fun setOnDayMoveListener(l: ((index: Boolean) -> Unit)): HeartDayChartOld {
        this.onDayMoveListener = l
        return this
    }

    /**
     * 设置是否显示0刻度线
     * @param show Boolean
     */
    fun setShowZeroLine(show: Boolean): HeartDayChartOld {
        this.showZeroLine = show
        postInvalidate()
        return this
    }

    /**
     * 设置是否显示底部滑块
     * @param show Boolean true显示滑块和指示器，false只显示时间文字
     */
    fun setShowSlider(show: Boolean): HeartDayChartOld {
        this.showSlider = show
        postInvalidate()
        return this
    }


    fun setShowYAxisLabel(show: Boolean): HeartDayChartOld {
        this.showYAxisLabels = show
        postInvalidate()  // 需要重新布局因为会影响图表宽度
        return this
    }
}